#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "sort.h"

#define DEFAULT_SCALE (1024)
#define DEFAULT_DIST (64)

static struct timeval start;
static struct timeval end;

#define CASE_START	gettimeofday(&start, NULL)
#define CASE_END	gettimeofday(&end, NULL)
#define CASE_COST	printf("cost: %ld\n", (end.tv_sec - start.tv_sec)*1000000 \
						+(end.tv_usec - start.tv_usec))

typedef int (*FUNCP)(int * array, int len);
static const char *mode_list[] = {"heap","insert","select","bubble","merge","quick", NULL};
static const FUNCP func_list[] = {heap_sort, insert_sort, select_sort, bubble_sort, merge_sort, quick_sort, NULL};

int array_init(int* array, int len, int range)
{
	srandom(time(NULL));
	int i = 0;
	for(i=0; i<len; i++){
		array[i] = random()%(range);
	}
	return 0;
}

int array_dump(int* array, int len)
{
	int i = 0;
	for(i=0; i<len; i++){
		printf("%d\t",array[i]);
		if((i+1)%8 == 0){
			printf("\n");
		}
	}
	printf("\n");
	return 0;
}

int main(int argc, char** argv)
{
	int ret = 0;
	FUNCP sort = NULL;
	int scale = 0;
	int dist = 0;
	int dump = 0;
	while( ( ret = getopt( argc, argv, "m:s:d:p" ) ) != EOF ){
		int i = 0;
		switch( ret ){
			case 'm'://sort mode
				for(i=0; mode_list[i]!=NULL; i++){
					if(!strcmp(optarg,mode_list[i])){
						sort = func_list[i];
					}
				}
				break;
			case 's'://array scale
				scale = atoi(optarg);
				break;
			case 'd'://random dist
				dist = atoi(optarg);
				break;
			case 'p'://dump
				dump = 1;
				break;
				break;
		}
	}
	if(scale <= 0){
		scale = DEFAULT_SCALE;
	}
	if(dist <= 0){
		dist = DEFAULT_DIST;
	}
	if(sort == NULL){
		printf("sort mode must be specified by -m\n");
		exit(1);
	}

	int *array = (int *)malloc(sizeof(int) * scale);
	array_init(array, scale, scale*dist);
	if(dump){
		array_dump(array, scale);
	}
	CASE_START;

	sort(array, scale);

	CASE_END;
	if(dump){
		array_dump(array, scale);
	}
	CASE_COST;
	return 0;
}

